
#include "VolumetricLinesApp.hpp"


void VolumetricLinesApp::updateFrame()
{
  m_camera->update();
    
  
  // --------
  
  
  // handles somes events
  if (aer::EventHandler::IsKeyPressed( sf::Keyboard::Escape )) quit();
  if (aer::EventHandler::IsKeyPressed( sf::Keyboard::F )) printf("fps : %u\n", m_timer.getFPS());
  
}


void VolumetricLinesApp::drawFrame()
{
  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  
  //glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
  
  
  //glEnable(GL_DEPTH_TEST);
  glEnable( GL_BLEND );
  
  glBlendEquation( GL_FUNC_ADD );
  glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  
  m_volumetricLinesPS.bind();
  {
    aer::Matrix4x4 mvp = m_camera->getViewProjectionMatrix();
    m_volumetricLinesPS.setUniform( "uModelViewProjMatrix", mvp);
    m_volumetricLinesPS.setUniform( "uRadius", 0.75f);
    m_lineStripMesh.draw();
  }
  m_volumetricLinesPS.unbind();
  
  glDisable( GL_BLEND );
}


// --------------------------------------

void VolumetricLinesApp::init()
{
  /// Init the camera
  aer::View view( aer::Vector3( 0.0f, 0.0f, +30.0f),
                  aer::Vector3( 0.0f, 0.0f, 0.0f),
                  aer::Vector3( 0.0f, 1.0f, 0.0f) );
 
  float ratio = m_Window->getDisplay().getAspectRatio();
  aer::Frustum frustum( 60.0f, ratio, 0.5f, 500.0f);

  m_camera = new aer::FreeCamera( view, frustum);
  m_camera->setMoveCoefficient( 1.7f );
  

  /// OpenGL settings
  glClearColor( 0.0f, 0.0f, 0.0f, 1.0f);
    
  initGeometry();
  initShader();
}


void VolumetricLinesApp::initGeometry()
{
  std::vector<aer::Vector3> linesPoints;
  std::vector<aer::Vector3> linesNormal;
  
  const size_t kNumSegments = 500;
  linesPoints.resize( kNumSegments );
  linesNormal.resize( kNumSegments );
  
  const int kNumSpin = 5;
  const float kLength = 100.0f;
  const float factor = 1.0f / float(kNumSegments-1);
  const float scale = 10.0f;
  
  for (int i=0; i<kNumSegments; ++i)
  {
    float alpha = 2.0f * M_PI * kNumSpin * factor;
    
    linesPoints[i].x = cos( alpha * i ) * scale;
    linesPoints[i].y = sin( alpha * i ) * scale;
    linesPoints[i].z = - kLength * (factor * i);
    
    linesNormal[i].x = - linesPoints[i].y/scale;
    linesNormal[i].y = + linesPoints[i].x/scale;
    linesNormal[i].z = kNumSegments;
    
    linesNormal[i] = glm::normalize(linesNormal[i]);
  }
  
  m_lineStripMesh.setAttrib( aer::Mesh::POSITION, (float*)linesPoints.data(), 3,
                             linesPoints.size());
  m_lineStripMesh.setAttrib( aer::Mesh::NORMAL, (float*)linesNormal.data(), 3,
                             linesNormal.size());
  
  m_lineStripMesh.setPrimitiveType( GL_LINE_STRIP_ADJACENCY );
  m_lineStripMesh.upload( aer::DeviceBuffer::STATIC_DRAW );
}


void VolumetricLinesApp::initShader()
{
  /// GLSW, shader file manager
  glswInit();  
 
 
  const char *kShadersPath = "../VolumetricLines/"; 
  glswSetPath( kShadersPath, ".glsl");
  
  glswAddDirectiveToken("*", "#version 330 core");    
  
  m_volumetricLinesPS.generate();
    m_volumetricLinesPS.addShader( aer::Program::VERTEX_SHADER,   "VolumetricLines.Vertex");
    m_volumetricLinesPS.addShader( aer::Program::GEOMETRY_SHADER, "VolumetricLines.Geometry");
    m_volumetricLinesPS.addShader( aer::Program::FRAGMENT_SHADER, "VolumetricLines.Fragment");
  m_volumetricLinesPS.link();
  
  
  glswShutdown();
}
